﻿//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
* 类 名 称 ：IEnumerableExtension
* 类 描 述 ：
* 作    者 ：henrychang
* 创建时间 ：2019/1/11 16:04:59
*******************************************************************
* Copyright @ henrychang 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using System;
using System.Collections.Generic;
using System.Linq;

public static class IEnumerableExtension
{
    #region Array Extension

    /// <summary>
    /// Fors the each.
    /// </summary>
    /// <returns>The each.</returns>
    /// <param name="selfArray">Self array.</param>
    /// <param name="action">Action.</param>
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    public static T[] ForEach<T>(this T[] selfArray, Action<T> action)
    {
        Array.ForEach(selfArray, action);
        return selfArray;
    }

    /// <summary>
    /// Fors the each.
    /// </summary>
    /// <returns>The each.</returns>
    /// <param name="selfArray">Self array.</param>
    /// <param name="action">Action.</param>
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> selfArray, Action<T> action)
    {
        if (action == null) throw new ArgumentException();
        foreach (var item in selfArray)
        {
            action(item);
        }

        return selfArray;
    }

    #endregion Array Extension

    #region List Extension

    /// <summary>
    /// Fors the each reverse.
    /// </summary>
    /// <returns>The each reverse.</returns>
    /// <param name="selfList">Self list.</param>
    /// <param name="action">Action.</param>
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    public static List<T> ForEachReverse<T>(this List<T> selfList, Action<T> action)
    {
        if (action == null) throw new ArgumentException();

        for (var i = selfList.Count - 1; i >= 0; --i)
            action(selfList[i]);

        return selfList;
    }

    /// <summary>
    /// Fors the each reverse.
    /// </summary>
    /// <returns>The each reverse.</returns>
    /// <param name="selfList">Self list.</param>
    /// <param name="action">Action.</param>
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    public static List<T> ForEachReverse<T>(this List<T> selfList, Action<T, int> action)
    {
        if (action == null) throw new ArgumentException();

        for (var i = selfList.Count - 1; i >= 0; --i)
            action(selfList[i], i);

        return selfList;
    }

    /// <summary>
    /// 遍历列表
    /// </summary>
    /// <typeparam name="T">列表类型</typeparam>
    /// <param name="list">目标表</param>
    /// <param name="action">行为</param>
    public static void ForEach<T>(this List<T> list, Action<int, T> action)
    {
        for (var i = 0; i < list.Count; i++)
        {
            action(i, list[i]);
        }
    }

    /// <summary>
    /// 拷贝到
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <param name="begin"></param>
    /// <param name="end"></param>
    public static void CopyTo<T>(this List<T> from, List<T> to, int begin = 0, int end = -1)
    {
        if (begin < 0)
        {
            begin = 0;
        }

        var endIndex = Math.Min(from.Count, to.Count) - 1;

        if (end != -1 && end < endIndex)
        {
            endIndex = end;
        }

        for (var i = begin; i < end; i++)
        {
            to[i] = from[i];
        }
    }

    /// <summary>
    /// 将List转为Array
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="selfList"></param>
    /// <returns></returns>
    public static T[] ToArraySavely<T>(this List<T> selfList)
    {
        var res = new T[selfList.Count];

        for (var i = 0; i < selfList.Count; i++)
        {
            res[i] = selfList[i];
        }

        return res;
    }

    /// <summary>
    /// 尝试获取，如果没有该数则返回null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="selfList"></param>
    /// <param name="index"></param>
    /// <returns></returns>
    public static T TryGet<T>(this List<T> selfList, int index)
    {
        return selfList.Count > index ? selfList[index] : default(T);
    }

    #endregion List Extension

    #region Dictionary Extension

    /// <summary>
    /// Merge the specified dictionary and dictionaries.
    /// </summary>
    /// <returns>The merge.</returns>
    /// <param name="dictionary">Dictionary.</param>
    /// <param name="dictionaries">Dictionaries.</param>
    /// <typeparam name="TKey">The 1st type parameter.</typeparam>
    /// <typeparam name="TValue">The 2nd type parameter.</typeparam>
    public static Dictionary<TKey, TValue> Merge<TKey, TValue>(this Dictionary<TKey, TValue> dictionary,
        params Dictionary<TKey, TValue>[] dictionaries)
    {
        return dictionaries.Aggregate(dictionary,
            (current, dict) => current.Union(dict).ToDictionary(kv => kv.Key, kv => kv.Value));
    }

    /// <summary>
    /// 遍历
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    /// <param name="dict"></param>
    /// <param name="action"></param>
    public static void ForEach<K, V>(this Dictionary<K, V> dict, Action<K, V> action)
    {
        var dictE = dict.GetEnumerator();

        while (dictE.MoveNext())
        {
            var current = dictE.Current;
            action(current.Key, current.Value);
        }

        dictE.Dispose();
    }

    /// <summary>
    /// 向其中添加新的词典
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    /// <param name="dict"></param>
    /// <param name="addInDict"></param>
    /// <param name="isOverride"></param>
    public static void AddRange<K, V>(this Dictionary<K, V> dict, Dictionary<K, V> addInDict,
        bool isOverride = false)
    {
        var dictE = addInDict.GetEnumerator();

        while (dictE.MoveNext())
        {
            var current = dictE.Current;
            if (dict.ContainsKey(current.Key))
            {
                if (isOverride)
                    dict[current.Key] = current.Value;
                continue;
            }

            dict.Add(current.Key, current.Value);
        }

        dictE.Dispose();
    }

    #endregion Dictionary Extension
}